The CIFileDialogEents class implements the
IFileDialogEvents interface, that exposes methods that
allow notification of events within a common file dialog.
The CIFileDialogControlEvents class implements the
IFileDialogControlEvents interface, that exposes methods
that allow an application to be notified of events that are related to
controls that the application has added to a common file dialog.
Include file: AfxNova/CIFileDialogEvents.inc
| Name | Description |
|---|---|
| OnFileOk | Called just before the dialog is about to return with a result. |
| OnFolderChange | Called when the user navigates to a new folder. |
| OnFolderChanging | Called before IFileDialogEvents::OnFolderChange. This allows the implementer to stop navigation to a particular location. |
| OnOverwrite | Called from the save dialog when the user chooses to overwrite a file. |
| OnSelectionChange | Called when the user changes the selection in the dialog’s view. |
| OnShareViolation | Enables an application to respond to sharing violations that arise from Open or Save operations. |
| OnTypeChange | Called when the dialog is opened to notify the application of the initial chosen filetype. |
| Name | Description |
|---|---|
| OnButtonClicked | Called when the user clicks a command button. |
| OnCheckButtonToggled | Called when the user changes the state of a check button (check box). |
| OnControlActivating | Called when an Open button drop-down list customized through EnableOpenDropDown or a Tools menu is about to display its contents. |
| OnItemSelected | Called when an item is selected in a combo box, when a user clicks an option button (also known as a radio button), or an item is chosen from the Tools menu. |
| Name | Description |
|---|---|
| Template | Template code that implements the FileDialogEvents callback interface. |
| Template2 | Template code that implements the FileDialogEvents and IFileDialogControlEvents callback interfaces. |
Called just before the dialog is about to return with a result.
FUNCTION OnFileOk (BYVAL pfd AS IFileDialog PTR) AS HRESULT
| Parameter | Description |
|---|---|
| pfd | A pointer to the interface that represents the dialog. |
Implementations should return S_OK to accept the current result in the dialog or S_FALSE to refuse it. In the case of S_FALSE, the dialog should remain open.
When this method is called, the GetResult, GetResultString and GetResults methods can be called.
The application can use this callback method to perform additional validation before the dialog closes, or to prevent the dialog from closing. If the application prevents the dialog from closing, it should display a UI to indicate a cause. To obtain a parent HWND for the UI, obtain the IOleWindow interface through IFileDialog.QueryInterface and call IOleWindow.GetWindow.
An application can also use this method to perform all of its work surrounding the opening or saving of files.
Called when the user navigates to a new folder.
FUNCTION OnFolderChange (BYVAL pfd AS IFileDialog PTR) AS HRESULT
| Parameter | Description |
|---|---|
| pfd | A pointer to the interface that represents the dialog. |
Returns S_OK if successful, or an error value otherwise.
OnFolderChange is called when the dialog is opened.
Called before OnFolderChange. This allows the implementer to stop navigation to a particular location.
FUNCTION OnFolderChanging (BYVAL pfd AS IFileDialog PTR, BYVAL psiFolder AS IShellItem PTR) AS HRESULT
| Parameter | Description |
|---|---|
| pfd | A pointer to the interface that represents the dialog. |
| psiFolder | A pointer to an interface that represents the folder to which the dialog is about to navigate. |
Returns S_OK if successful, or an error value otherwise. A return value of S_OK or E_NOTIMPL indicates that the folder change can proceed.
Called from the save dialog when the user chooses to overwrite a file.
FUNCTION OnOverwrite (BYVAL pfd AS IFileDialog PTR, BYVAL psi AS IShellItem PTR, _
BYVAL pResponse AS FDE_OVERWRITE_RESPONSE PTR) AS HRESULT
| Parameter | Description |
|---|---|
| pfd | A pointer to the interface that represents the dialog. |
| psi | A pointer to the interface that represents the item that will be overwritten. |
| pResponse | A pointer to a value from the FDE_OVERWRITE_RESPONSE enumeration indicating the response to the potential overwrite action. |
FDE_OVERWRITE_RESPONSE enumeration
| Flag | Value | Description |
|---|---|---|
| FDEOR_DEFAULT | 0 | The application has not handled the event. The dialog displays a UI asking the user whether the file should be overwritten and returned from the dialog. |
| FDEOR_ACCEPT | 1 | The application has determined that the file should be returned from the dialog. |
| FDEOR_REFUSE | 2 | The application has determined that the file should not be returned from the dialog. |
The implementer should return E_NOTIMPL if this method is not implemented; S_OK or an appropriate error code otherwise.
The FOS_OVERWRITEPROMPT flag must be set through IFileDialog.SetOptions before this method is called.
Called when the user changes the selection in the dialog’s view.
FUNCTION OnSelectionChange (BYVAL pfd AS IFileDialog PTR) AS HRESULT
| Parameter | Description |
|---|---|
| pfd | A pointer to the interface that represents the dialog. |
If this method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.
Enables an application to respond to sharing violations that arise from Open or Save operations.
FUNCTION OnShareViolation (BYVAL pfd AS IFileDialog PTR, BYVAL psi AS IShellItem PTR, _
BYVAL pResponse AS FDE_SHAREVIOLATION_RESPONSE PTR) AS HRESULT
| Parameter | Description |
|---|---|
| pfd | A pointer to the interface that represents the dialog. |
| psi | A pointer to the interface that represents the item that has the sharing violation. |
| pResponse | A pointer to a value from the FDE_SHAREVIOLATION_RESPONSE enumeration indicating the response to the sharing violation. |
FDE_SHAREVIOLATION_RESPONSE enumeration
| Flag | Value | Description |
|---|---|---|
| FDESVR_DEFAULT | 0 | The application has not handled the event. The dialog displays a UI that indicates that the file is in use and a different file must be chosen. |
| FDESVR_ACCEPT | 1 | The application has determined that the file should be returned from the dialog. |
| FDESVR_REFUSE | 2 | The application has determined that the file should not be returned from the dialog. |
The implementer should return E_NOTIMPL if this method is not implemented; S_OK or an appropriate error code otherwise.
The FOS_SHAREAWARE flag must be set through IFileDialog.SetOptions before this method is called.
A sharing violation could possibly arise when the application attempts to open a file, because the file could have been locked between the time that the dialog tested it and the application opened it.
Called when the dialog is opened to notify the application of the initial chosen filetype.
FUNCTION OnTypeChange (BYVAL pfd AS IFileDialog PTR) AS HRESULT
| Parameter | Description |
|---|---|
| pfd | A pointer to the interface that represents the dialog. |
Returns S_OK if successful, or an error value otherwise.
Called when the user clicks a command button.
FUNCTION OnButtonClicked (BYVAL pfdc AS IFileDialogCustomize PTR, BYVAL dwIDCtl AS DWORD) AS HRESULT
| Parameter | Description |
|---|---|
| pfdc | A pointer to the interface through which the application added controls to the dialog. |
| dwIDCtl | The ID of the button that the user clicked. |
If this method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.
Called when the user changes the state of a check button (check box).
FUNCTION OnCheckButtonToggled (BYVAL pfdc AS IFileDialogCustomize PTR, _
BYVAL dwIDCtl AS DWORD, BYVAL bChecked AS WINBOOL) AS HRESULT
| Parameter | Description |
|---|---|
| pfdc | A pointer to the interface through which the application added controls to the dialog. |
| dwIDCtl | The ID of the button that the user clicked. |
| bChecked | A BOOL indicating the current state of the check button. TRUE if checked; FALSE otherwise. |
If this method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.
Called when an Open button drop-down list customized through EnableOpenDropDown or a Tools menu is about to display its contents.
FUNCTION OnControlActivating (BYVAL pfdc AS IFileDialogCustomize PTR, BYVAL dwIDCtl AS DWORD) AS HRESULT
| Parameter | Description |
|---|---|
| pfdc | A pointer to the interface through which the application added controls to the dialog. |
| dwIDCtl | The ID of the list or menu about to display. |
If this method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.
The following template implements the FileDialogEvents callback interface.
' ########################################################################################
' CIFileDialogEvents class
' Implementation of the FileDialogEvents callback interface
' ########################################################################################
TYPE CIFileDialogEvents EXTENDS OBJECT
DECLARE VIRTUAL FUNCTION QueryInterface (BYVAL riid AS REFIID, BYVAL ppvObject AS LPVOID PTR) AS HRESULT
DECLARE VIRTUAL FUNCTION AddRef () AS ULONG
DECLARE VIRTUAL FUNCTION Release () AS ULONG
DECLARE VIRTUAL FUNCTION OnFileOk (BYVAL pfd AS IFileDialog PTR) AS HRESULT
DECLARE VIRTUAL FUNCTION OnFolderChanging (BYVAL pfd AS IFileDialog PTR, BYVAL psiFolder AS IShellItem PTR) AS HRESULT
DECLARE VIRTUAL FUNCTION OnFolderChange (BYVAL pfd AS IFileDialog PTR) AS HRESULT
DECLARE VIRTUAL FUNCTION OnSelectionChange (BYVAL pfd AS IFileDialog PTR) AS HRESULT
DECLARE VIRTUAL FUNCTION OnShareViolation (BYVAL pfd AS IFileDialog PTR, BYVAL psi AS IShellItem PTR, BYVAL pResponse AS FDE_SHAREVIOLATION_RESPONSE PTR) AS HRESULT
DECLARE VIRTUAL FUNCTION OnTypeChange (BYVAL pfd AS IFileDialog PTR) AS HRESULT
DECLARE VIRTUAL FUNCTION OnOverwrite (BYVAL pfd AS IFileDialog PTR, BYVAL psi AS IShellItem PTR, BYVAL pResponse AS FDE_OVERWRITE_RESPONSE PTR) AS HRESULT
DECLARE CONSTRUCTOR
DECLARE DESTRUCTOR
' Reference count for COM
refCount AS ULONG = 0
END TYPE
' ########################################################################################
' ########################################################################################
' Template example to set a IFileDialogEvents innterface.
' ########################################################################################
' =====================================================================================
' Constructor
' =====================================================================================
PRIVATE CONSTRUCTOR CIFileDialogEvents
END CONSTRUCTOR
' =====================================================================================
' =====================================================================================
' Destructor
' =====================================================================================
PRIVATE DESTRUCTOR CIFileDialogEvents
END DESTRUCTOR
' =====================================================================================
' *** IUnknown interface methods ***
' ========================================================================================
' Returns pointers to the implemented classes and supported interfaces.
' ========================================================================================
PRIVATE FUNCTION CIFileDialogEvents.QueryInterface (BYVAL riid AS REFIID, BYVAL ppvObj AS LPVOID PTR) AS HRESULT
COSFD_DP("riid: " & AfxGuidText(riid))
IF ppvObj = NULL THEN RETURN E_INVALIDARG
IF IsEqualIID(riid, @IID_IFileOpenDialog) OR _
IsEqualIID(riid, @IID_IFileSaveDialog) OR _
IsEqualIID(riid, @IID_IUnknown) THEN
*ppvObj = @this
' // Increment the reference count
this.AddRef
RETURN S_OK
ELSE
IF IsEqualIID(riid, @IID_IFileDialogControlEvents) THEN
DIM pIFileDialogControlEvents AS CIFileDialogControlEvents PTR = NEW CIFileDialogControlEvents
pIFileDialogControlEvents->AddRef
*ppvObj = CAST(ANY PTR, pIFileDialogControlEvents)
RETURN S_OK
END IF
END IF
RETURN E_NOINTERFACE
END FUNCTION
' =====================================================================================
' ========================================================================================
' Increments the reference count for an interface on an object. This method should be called
' for every new copy of a pointer to an interface on an object.
' ========================================================================================
PRIVATE FUNCTION CIFileDialogEvents.AddRef () AS ULONG
refCount += 1
OutputDebugStringW("CIFileDialogEvents.AddRef " & ..WSTR(refCount))
RETURN refCount
END FUNCTION
' ========================================================================================
' ========================================================================================
' Decrements the reference count for an interface on an object.
' If the count reaches 0, it deletes itself.
' ========================================================================================
PRIVATE FUNCTION CIFileDialogEvents.Release () AS ULONG
refCount -= 1
IF refCount = 0 THEN
Delete @this
END IF
RETURN refCount
END FUNCTION
' =====================================================================================
' *** Event Handlers ***
' =====================================================================================
' Called just before the dialog is about to return with a result.
' When this method is called, the IFileDialog::GetResult and GetResults methods can be called.
' =====================================================================================
PRIVATE FUNCTION CIFileDialogEvents.OnFileOk (BYVAL pfd AS IFileDialog PTR) AS HRESULT
RETURN S_OK
END FUNCTION
' =====================================================================================
' =====================================================================================
' Called before OnFolderChange. This allows the implementer to stop navigation to a particular location.
' A pointer to an interface that represents the folder to which the dialog is about to navigate.
' =====================================================================================
PRIVATE FUNCTION CIFileDialogEvents.OnFolderChanging (BYVAL pfd AS IFileDialog PTR, _
BYVAL psiFolder AS IShellItem PTR) AS HRESULT
RETURN S_OK
END FUNCTION
' =====================================================================================
' =====================================================================================
' Called when the user navigates to a new folder.
' OnFolderChange is called when the dialog is opened.
' The code below allows to set the position of the dialog, but can't center it because
' the width and height of the dialog isn't settled until it is displayed.
' =====================================================================================
PRIVATE FUNCTION CIFileDialogEvents.OnFolderChange (BYVAL pfd AS IFileDialog PTR) AS HRESULT
' ' // Before displaying the dialog get its coordinates
' DIM pOleWindow AS IOleWindow PTR
' ' // Get a pointer to the IOleWindow interface
' pfd->lpvtbl->QueryInterface(pfd, @IID_IOleWindow, @pOleWindow)
' ' // Get the window handle of the dialog
' DIM hOleWindow AS HWND
' IF pOleWindow THEN pOleWindow->lpvtbl->GetWindow(pOleWindow, @hOleWindow)
' OutputDebugStringW("CIFileDialogEvents.OnFolderChange - hOleWindow: " & ..WSTR(hOleWindow))
' IF hOleWindow THEN
' ' // Get he bounding rectangle of the parent window
' DIM AS RECT rcDlg, rcOwner
' GetWindowRect(GetParent(hOleWindow), @rcOwner)
' ' // Get he bounding rectangle of the open file dialog
' GetWindowRect(hOleWindow, @rcDlg)
' ' // Maps the open file dialog coordinates relative to its parent window
' MapWindowPoints(GetParent(hOleWindow), hOleWindow, CAST(POINT PTR, @rcDlg), 2)
' END IF
RETURN S_OK
END FUNCTION
' =====================================================================================
' =====================================================================================
' Called when the user changes the selection in the dialog's view.
' =====================================================================================
PRIVATE FUNCTION CIFileDialogEvents.OnSelectionChange (BYVAL pfd AS IFileDialog PTR) AS HRESULT
RETURN S_OK
END FUNCTION
' =====================================================================================
' =====================================================================================
' Enables an application to respond to sharing violations that arise from Open or Save operations.
' =====================================================================================
PRIVATE FUNCTION CIFileDialogEvents.OnShareViolation (BYVAL pfd AS IFileDialog PTR, _
BYVAL psi AS IShellItem PTR, BYVAL pResponse AS FDE_SHAREVIOLATION_RESPONSE PTR) AS HRESULT
RETURN S_OK
END FUNCTION
' =====================================================================================
' =====================================================================================
' Called when the dialog is opened to notify the application of the initial chosen filetype.
' =====================================================================================
PRIVATE FUNCTION CIFileDialogEvents.OnTypeChange (BYVAL pfd AS IFileDialog PTR) AS HRESULT
RETURN S_OK
END FUNCTION
' =====================================================================================
' =====================================================================================
' Called from the save dialog when the user chooses to overwrite a file.
' =====================================================================================
PRIVATE FUNCTION CIFileDialogEvents.OnOverwrite (BYVAL pfd AS IFileDialog PTR, _
BYVAL psi AS IShellItem PTR, BYVAL pResponse AS FDE_OVERWRITE_RESPONSE PTR) AS HRESULT
RETURN S_OK
END FUNCTION
' =====================================================================================
Example of how to override the template with yur own class:
' ########################################################################################
' CIFileDialogEventsImpl class
' Implementation of the FileDialogEvents callback interface
' ########################################################################################
TYPE CIFileDialogEventsImpl EXTENDS CIFileDialogEvents
DECLARE FUNCTION OnFolderChange (BYVAL pfd AS IFileDialog PTR) AS HRESULT
END TYPE
PRIVATE FUNCTION CIFileDialogEventsImpl.OnFolderChange (BYVAL pfd AS IFileDialog PTR) AS HRESULT
' // Before displaying the dialog get its coordinates
DIM pOleWindow AS IOleWindow PTR
' // Get a pointer to the IOleWindow interface
pfd->lpvtbl->QueryInterface(pfd, @IID_IOleWindow, @pOleWindow)
' // Get the window handle of the dialog
DIM hOleWindow AS HWND
IF pOleWindow THEN pOleWindow->lpvtbl->GetWindow(pOleWindow, @hOleWindow)
OutputDebugStringW ("CIFileDialogEventsImpl.OnFolderChange - hOleWindow: " & ..WSTR(hOleWindow))
IF hOleWindow THEN
' // Get he bounding rectangle of the parent window
DIM AS RECT rcDlg, rcOwner
GetWindowRect(GetParent(hOleWindow), @rcOwner)
' // Get he bounding rectangle of the open file dialog
GetWindowRect(hOleWindow, @rcDlg)
' // Maps the open file dialog coordinates relative to its parent window
MapWindowPoints(GetParent(hOleWindow), hOleWindow, CAST(POINT PTR, @rcDlg), 2)
END IF
RETURN S_OK
END FUNCTION
' ========================================================================================
Set the events to your class with the SetEvents method:
' // Set events
DIM pfde AS ANY PTR = NEW CIFileDialogEventsImpl
pofd.SetEvents(pfde)
DIM pofd AS CIOpenFileDialog
' // Set the file types
pofd.AddFileType("FB code files", "*.bas;*.inc;*.bi")
pofd.AddFileType("Executable files", "*.exe;*.dll")
pofd.AddFileType("All files", "*.*")
pofd.SetFileTypes()
' // Multiple selection (default is single selection)
DIM options AS FILEOPENDIALOGOPTIONS = pofd.GetOptions
pofd.SetOptions(options OR FOS_ALLOWMULTISELECT)
' // Optional: Set the title of the dialog
' pofd.SetTitle("A Single-Selection Dialog")
' // Set the folder
pofd.SetFolder(CURDIR)
pofd.SetDefaultExtension("bas")
pofd.SetFileTypeIndex(1)
' // Set events
DIM pfde AS ANY PTR = NEW CIFileDialogEventsImpl
pofd.SetEvents(pfde)
' // Display the dialog
DIM hr AS HRESULT = pofd.ShowOpen(hwnd)
' // Folder name
OutputDebugStringW("Folder name: " & pofd.GetFolder)
' *** Single selection ***
' // Get the result
'IF hr = S_OK THEN
' print pofd.GetResultString
'END IF
' *** Multiple selection ***
IF hr = S_OK THEN
DIM dwsRes AS DWSTRING = pofd.GetResultsString
FOR i AS LONG = 1 TO pofd.GetResultsCount
OutputDebugStringW pofd.ParseResults(dwsRes, i)
NEXT
END IF
You can use the same class of the Save file dialog:
' ########################################################################################
' CIFileDialogEventsImpl class
' Implementation of the FileDialogEvents callback interface
' ########################################################################################
TYPE CIFileDialogEventsImpl EXTENDS CIFileDialogEvents
DECLARE FUNCTION OnFolderChange (BYVAL pfd AS IFileDialog PTR) AS HRESULT
DECLARE FUNCTION OnFileOk (BYVAL pfd AS IFileDialog PTR) AS HRESULT
END TYPE
PRIVATE FUNCTION CIFileDialogEventsImpl.OnFolderChange (BYVAL pfd AS IFileDialog PTR) AS HRESULT
RETURN S_OK
END FUNCTION
PRIVATE FUNCTION CIFileDialogEventsImpl.OnFileOk (BYVAL pfd AS IFileDialog PTR) AS HRESULT
RETURN S_OK
END FUNCTION
' ########################################################################################
Setting the event’s handler:
DIM psfd AS CISaveFileDialog
' // Set the file types
psfd.AddFileType("FB code files", "*.bas;*.inc;*.bi")
psfd.AddFileType("Executable files", "*.exe;*.dll")
psfd.AddFileType("All files", "*.*")
psfd.SetFileTypes()
' // Optional: Set the title of the dialog
' psfd.SetTitle("Save File Dialog")
' // Set the folder
psfd.SetFolder(CURDIR)
psfd.SetDefaultExtension("bas")
psfd.SetFileTypeIndex(1)
' // Set events
DIM pfde AS ANY PTR = NEW CIFileDialogEventsImpl
psfd.SetEvents(pfde)
' // Display the dialog
DIM hr AS HRESULT = psfd.ShowSave(hwnd)
' // Folder name
OutputDebugStringW("Folder name: " & psfd.GetFolder)
' // Get the result
IF hr = S_OK THEN
OutputDebugStringW(psfd.GetResultString)
END IF
The following template implements the FileDialogEvents and IFileDialogControlEvents callback interfaces.
' ########################################################################################
' Microsoft Windows
' File: CW_CIOpenFileDialog_Events_02.bas
' Contents: Open file dialog with dialog and control events
' Compiler: FreeBasic 32 & 64 bit
' Copyright (c) 2025 José© Roca. Freeware. Use at your own risk.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################
#define _WIN32_WINNT &h0602
#define _COSFD_DEBUG_ 1
#include once "AfxNova/CWindow.inc"
#include once "AfxNova/AfxCOM.inc"
#include once "AfxNova/CIOpenSaveFile.inc"
#include once "AfxNova/CIFileDialogCustomize.inc"
#include once "AfxNova/CIFileDialogEvents.inc"
USING AfxNova
CONST IDC_RICHEDIT = 1001
CONST IDC_TEST = 1002
DECLARE FUNCTION wWinMain (BYVAL hInstance AS HINSTANCE, _
BYVAL hPrevInstance AS HINSTANCE, _
BYVAL pwszCmdLine AS WSTRING PTR, _
BYVAL nCmdShow AS LONG) AS LONG
END wWinMain(GetModuleHandleW(NULL), NULL, wCommand(), SW_NORMAL)
' // Forward declaration
DECLARE FUNCTION WndProc (BYVAL hwnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT
' ========================================================================================
' Main
' ========================================================================================
FUNCTION wWinMain (BYVAL hInstance AS HINSTANCE, _
BYVAL hPrevInstance AS HINSTANCE, _
BYVAL pwszCmdLine AS WSTRING PTR, _
BYVAL nCmdShow AS LONG) AS LONG
' // Set process DPI aware
SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE)
' // Enable visual styles without including a manifest file
AfxEnableVisualStyles
DIM pWindow AS CWindow
DIM hWin AS HWND = pWindow.Create(NULL, "DisplayIOpenFile", @WndProc)
pWindow.SetClientSize(800, 450)
pWindow.Center
' // Add buttons
pWindow.AddControl("Button", hWin, IDC_TEST, "&Test", pWindow.ClientWidth - 195, pWindow.ClientHeight - 35, 75, 23)
pWindow.AddControl("Button", hWin, IDCANCEL, "&Close", pWindow.ClientWidth - 95, pWindow.ClientHeight - 35, 75, 23)
' // Anchor the controls
pWindow.AnchorControl(IDC_TEST, AFX_ANCHOR_BOTTOM_RIGHT)
pWindow.AnchorControl(IDCANCEL, AFX_ANCHOR_BOTTOM_RIGHT)
' // Dispatch Windows messages
FUNCTION = pWindow.DoEvents(nCmdShow)
END FUNCTION
' ========================================================================================
' ########################################################################################
' CIFileDialogControlEventsImpl class
' Implementation of the IFileDialogControlEvents callback interface
' ########################################################################################
TYPE CIFileDialogControlEventsImpl EXTENDS CIFileDialogControlEvents
DECLARE FUNCTION OnItemSelected (BYVAL pfdc AS IFileDialogCustomize PTR, BYVAL dwIDCtl AS DWORD, BYVAL dwIDItem AS DWORD) AS HRESULT
DECLARE FUNCTION OnButtonClicked (BYVAL pfdc AS IFileDialogCustomize PTR, BYVAL dwIDCtl AS DWORD) AS HRESULT
DECLARE FUNCTION OnCheckButtonToggled (BYVAL pfdc AS IFileDialogCustomize PTR, BYVAL dwIDCtl AS DWORD, BYVAL bChecked AS WINBOOL) AS HRESULT
DECLARE FUNCTION OnControlActivating (BYVAL pfdc AS IFileDialogCustomize PTR, BYVAL dwIDCtl AS DWORD) AS HRESULT
END TYPE
' // Override the virtual methods
' ========================================================================================
PRIVATE FUNCTION CIFileDialogControlEventsImpl.OnItemSelected (BYVAL pfdc AS IFileDialogCustomize PTR, BYVAL dwIDCtl AS DWORD, BYVAL dwIDItem AS DWORD) AS HRESULT
COSFD_DP("")
RETURN S_OK
END FUNCTION
' ========================================================================================
' ========================================================================================
' ========================================================================================
PRIVATE FUNCTION CIFileDialogControlEventsImpl.OnButtonClicked (BYVAL pfdc AS IFileDialogCustomize PTR, BYVAL dwIDCtl AS DWORD) AS HRESULT
COSFD_DP("")
RETURN S_OK
END FUNCTION
' ========================================================================================
' ========================================================================================
' ========================================================================================
PRIVATE FUNCTION CIFileDialogControlEventsImpl.OnCheckButtonToggled (BYVAL pfdc AS IFileDialogCustomize PTR, BYVAL dwIDCtl AS DWORD, BYVAL bChecked AS WINBOOL) AS HRESULT
COSFD_DP("")
RETURN S_OK
END FUNCTION
' ========================================================================================
' ========================================================================================
' ========================================================================================
PRIVATE FUNCTION CIFileDialogControlEventsImpl.OnControlActivating (BYVAL pfdc AS IFileDialogCustomize PTR, BYVAL dwIDCtl AS DWORD) AS HRESULT
COSFD_DP("")
RETURN S_OK
END FUNCTION
' ========================================================================================
' ########################################################################################
' CIFileDialogEventsImpl class
' Implementation of the FileDialogEvents callback interface
' ########################################################################################
TYPE CIFileDialogEventsImpl EXTENDS CIFileDialogEvents
DECLARE FUNCTION QueryInterface (BYVAL riid AS REFIID, BYVAL ppvObj AS LPVOID PTR) AS HRESULT
DECLARE FUNCTION OnFolderChange (BYVAL pfd AS IFileDialog PTR) AS HRESULT
DECLARE FUNCTION OnItemSelected (BYVAL pfdc AS IFileDialogCustomize PTR, BYVAL dwIDCtl AS DWORD, BYVAL dwIDItem AS DWORD) AS HRESULT
END TYPE
' ========================================================================================
' Returns pointers to the implemented classes and supported interfaces.
' ========================================================================================
PRIVATE FUNCTION CIFileDialogEventsImpl.QueryInterface (BYVAL riid AS REFIID, BYVAL ppvObj AS LPVOID PTR) AS HRESULT
COSFD_DP(AfxGuidText(riid))
IF ppvObj = NULL THEN RETURN E_INVALIDARG
IF IsEqualIID(riid, @IID_IFileOpenDialog) OR _
IsEqualIID(riid, @IID_IFileSaveDialog) OR _
IsEqualIID(riid, @IID_IUnknown) THEN
*ppvObj = @this
' // Increment the reference count
this.AddRef
RETURN S_OK
ELSE
IF IsEqualIID(riid, @IID_IFileDialogControlEvents) THEN
' // Create an instance of our implemented IFileDialogControlEvents interface
DIM pIFileDialogControlEvents AS CIFileDialogControlEventsImpl PTR = NEW CIFileDialogControlEventsImpl
' // Increment the reference count
pIFileDialogControlEvents->AddRef
' // Return a pointer to the event's class
*ppvObj = CAST(ANY PTR, pIFileDialogControlEvents)
RETURN S_OK
END IF
END IF
RETURN E_NOINTERFACE
END FUNCTION
' =====================================================================================
PRIVATE FUNCTION CIFileDialogEventsImpl.OnFolderChange (BYVAL pfd AS IFileDialog PTR) AS HRESULT
' // Before displaying the dialog get its coordinates
DIM pOleWindow AS IOleWindow PTR
' // Get a pointer to the IOleWindow interface
pfd->lpvtbl->QueryInterface(pfd, @IID_IOleWindow, @pOleWindow)
' // Get the window handle of the dialog
DIM hOleWindow AS HWND
IF pOleWindow THEN pOleWindow->lpvtbl->GetWindow(pOleWindow, @hOleWindow)
COSFD_DP ("hOleWindow: " & WSTR(hOleWindow))
IF hOleWindow THEN
' // Get he bounding rectangle of the parent window
DIM AS RECT rcDlg, rcOwner
GetWindowRect(GetParent(hOleWindow), @rcOwner)
' // Get he bounding rectangle of the open file dialog
GetWindowRect(hOleWindow, @rcDlg)
' // Maps the open file dialog coordinates relative to its parent window
MapWindowPoints(GetParent(hOleWindow), hOleWindow, CAST(POINT PTR, @rcDlg), 2)
END IF
RETURN S_OK
END FUNCTION
' ########################################################################################
' ========================================================================================
' Main window callback procedure
' ========================================================================================
FUNCTION WndProc (BYVAL hwnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT
STATIC hFocus AS HWND
SELECT CASE uMsg
CASE WM_NCACTIVATE
' // Save the handle of the control that has the focus
IF wParam = 0 THEN hFocus = GetFocus
' // Note: Don't use EXIT FUNCTION
CASE WM_SETFOCUS
' // Post a message to set the focus later, since some
' // Windows actions can steal it if we set it here
IF hFocus THEN
PostMessage hWnd, WM_USER + 999, cast(WPARAM, hFocus), 0
hFocus = 0
END IF
CASE WM_USER + 999
' // Set the focus and show the line an column in the status bar
IF wParam THEN SetFocus(cast(HWND, wParam))
EXIT FUNCTION
CASE WM_SYSCOMMAND
' // Capture this message and send a WM_CLOSE message
IF (wParam AND &HFFF0) = SC_CLOSE THEN
SendMessage hwnd, WM_CLOSE, 0, 0
EXIT FUNCTION
END IF
CASE WM_COMMAND
SELECT CASE GET_WM_COMMAND_ID(wParam, lParam)
' // If ESC key pressed, close the application sending an WM_CLOSE message
CASE IDCANCEL
IF GET_WM_COMMAND_CMD(wParam, lParam) = BN_CLICKED THEN
SendMessageW hwnd, WM_CLOSE, 0, 0
EXIT FUNCTION
END IF
' // For testing purposes
CASE IDC_TEST
SCOPE
DIM pofd AS CIOpenFileDialog
' // Set the file types
pofd.AddFileType("FB code files", "*.bas;*.inc;*.bi")
pofd.AddFileType("Executable files", "*.exe;*.dll")
pofd.AddFileType("All files", "*.*")
pofd.SetFileTypes()
' // Multiple selection (default is single selection)
DIM options AS FILEOPENDIALOGOPTIONS = pofd.GetOptions
pofd.SetOptions(options OR FOS_ALLOWMULTISELECT)
' // Optional: Set the title of the dialog
' pofd.SetTitle("A Single-Selection Dialog")
' // Set the folder
pofd.SetFolder(CURDIR)
pofd.SetDefaultExtension("bas")
pofd.SetFileTypeIndex(1)
' // Customization
' // Get a pointer to the IFileDialog interface
DIM pfdlg AS IFileDialog PTR = pofd.GetIFileDialogPtr
IF pfdlg THEN
' // Initialize an instance of the CIFileDialogCustomize class
DIM pCust AS CIFileDialogCustomize = pfdlg
' // Relese the IFileDialog interface
pfdlg->lpvtbl->Release(pfdlg)
' // Add controls to the dialog
IF pCust.GetPtr THEN
' Call methods of the CIFileDialogCustomize class
pCust.AddCheckButton(1001, "My check button", TRUE)
pCust.AddComboBox(1002)
pCust.AddEditBox(1003, "My edit control")
pCust.AddMenu(1004, "My menu")
pCust.AddPushButton(1005, "My push button")
pCust.AddSeparator(1006)
pCust.AddText(1007, "My text")
pCust.EnableOpenDropDown(1008)
END IF
END IF
' // Set events
DIM pfde AS ANY PTR = NEW CIFileDialogEventsImpl
pofd.SetEvents(pfde)
' // Display the dialog
DIM hr AS HRESULT = pofd.ShowOpen(hwnd)
' // Folder name
OutputDebugStringW("Folder name: " & pofd.GetFolder)
' *** Single selection ***
' // Get the result
'IF hr = S_OK THEN
' OutputDebugStringW pofd.GetResult()
'END IF
' *** Multiple selection ***
IF hr = S_OK THEN
DIM dwsRes AS DWSTRING = pofd.GetResultsString
FOR i AS LONG = 1 TO pofd.GetResultsCount
OutputDebugStringW pofd.ParseResults(dwsRes, i)
NEXT
END IF
END SCOPE
END SELECT
CASE WM_DESTROY
' // End the application by sending an WM_QUIT message
PostQuitMessage(0)
EXIT FUNCTION
END SELECT
' // Default processing of Windows messages
FUNCTION = DefWindowProcW(hWnd, uMsg, wParam, lParam)
END FUNCTION
' ========================================================================================